gdkbroadway-server.h \
broadway-protocol.h \
gdkbroadway-server.c \
- broadway.h \
- broadway.c
+ broadway-output.h \
+ broadway-output.c
clienthtml.h: client.html
$(PERL) $(srcdir)/toarray.pl $(srcdir)/client.html client_html > $@
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <cairo.h>
+
+#include "broadway-output.h"
+
+/************************************************************************
+ * Base64 functions *
+ ************************************************************************/
+
+static const char base64_alphabet[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#if 0 /* Unused for now */
+static void
+base64_uint8 (guint8 v, char *c)
+{
+ c[0] = base64_alphabet[(v >> 0) & 0x3f];
+ c[1] = base64_alphabet[(v >> 6) & 0x3];
+}
+#endif
+
+static void
+base64_uint16 (guint32 v, char *c)
+{
+ c[0] = base64_alphabet[(v >> 0) & 0x3f];
+ c[1] = base64_alphabet[(v >> 6) & 0x3f];
+ c[2] = base64_alphabet[(v >> 12) & 0xf];
+}
+
+#if 0
+static void
+base64_uint24 (guint32 v, char *c)
+{
+ c[0] = base64_alphabet[(v >> 0) & 0x3f];
+ c[1] = base64_alphabet[(v >> 6) & 0x3f];
+ c[2] = base64_alphabet[(v >> 12) & 0x3f];
+ c[3] = base64_alphabet[(v >> 18) & 0x3f];
+}
+#endif
+
+static void
+base64_uint32 (guint32 v, char *c)
+{
+ c[0] = base64_alphabet[(v >> 0) & 0x3f];
+ c[1] = base64_alphabet[(v >> 6) & 0x3f];
+ c[2] = base64_alphabet[(v >> 12) & 0x3f];
+ c[3] = base64_alphabet[(v >> 18) & 0x3f];
+ c[4] = base64_alphabet[(v >> 24) & 0x3f];
+ c[5] = base64_alphabet[(v >> 30) & 0x2];
+}
+
+/***********************************************************
+ * conversion of raw image data to png data: uris *
+ ***********************************************************/
+
+static cairo_status_t
+write_png_data (void *closure,
+ const unsigned char *data,
+ unsigned int data_len)
+{
+ GString *buf = closure;
+
+ g_string_append_len (buf, (char *)data, data_len);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+to_png_rgb (GString *buf, int w, int h, int byte_stride, guint32 *data)
+{
+ cairo_surface_t *surface;
+
+ surface = cairo_image_surface_create_for_data ((guchar *)data,
+ CAIRO_FORMAT_RGB24, w, h, byte_stride);
+
+ cairo_surface_write_to_png_stream (surface, write_png_data, buf);
+ cairo_surface_destroy (surface);
+}
+
+static void
+to_png_rgba (GString *buf, int w, int h, int byte_stride, guint32 *data)
+{
+ cairo_surface_t *surface;
+
+ surface = cairo_image_surface_create_for_data ((guchar *)data,
+ CAIRO_FORMAT_ARGB32, w, h, byte_stride);
+
+ cairo_surface_write_to_png_stream (surface, write_png_data, buf);
+ cairo_surface_destroy (surface);
+}
+
+struct PngTarget {
+ GString *buf;
+ int state;
+ int save;
+};
+
+static cairo_status_t
+write_png_url (void *closure,
+ const unsigned char *data,
+ unsigned int data_len)
+{
+ struct PngTarget *target = closure;
+ gsize res, old_len;
+
+ old_len = target->buf->len;
+ g_string_set_size (target->buf,
+ old_len + (data_len / 3 + 1) * 4 + 4);
+
+ res = g_base64_encode_step (data, data_len, FALSE,
+ target->buf->str + old_len,
+ &target->state, &target->save);
+
+ g_string_set_size (target->buf, old_len + res);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+to_png_url_rgb (GString *buf, int w, int h, int byte_stride, guint32 *data)
+{
+ cairo_surface_t *surface;
+ struct PngTarget target;
+ gsize res, old_len;
+
+ target.buf = buf;
+ target.state = 0;
+ target.save = 0;
+
+ g_string_append (buf, "data:image/png;base64,");
+
+ surface = cairo_image_surface_create_for_data ((guchar *)data,
+ CAIRO_FORMAT_RGB24, w, h, byte_stride);
+
+ cairo_surface_write_to_png_stream (surface, write_png_url, &target);
+ cairo_surface_destroy (surface);
+
+ old_len = buf->len;
+
+ g_string_set_size (buf, old_len + 4);
+ res = g_base64_encode_close (FALSE,
+ buf->str + old_len,
+ &target.state, &target.save);
+ g_string_set_size (buf, old_len + res);
+}
+
+static void
+to_png_url_rgba (GString *buf, int w, int h, int byte_stride, guint32 *data)
+{
+ cairo_surface_t *surface;
+ struct PngTarget target;
+ gsize res, old_len;
+
+ target.buf = buf;
+ target.state = 0;
+ target.save = 0;
+
+ g_string_append (buf, "data:image/png;base64,");
+
+ surface = cairo_image_surface_create_for_data ((guchar *)data,
+ CAIRO_FORMAT_ARGB32, w, h, byte_stride);
+
+ cairo_surface_write_to_png_stream (surface, write_png_url, &target);
+ cairo_surface_destroy (surface);
+
+ old_len = buf->len;
+
+ g_string_set_size (buf, old_len + 4);
+ res = g_base64_encode_close (FALSE,
+ buf->str + old_len,
+ &target.state, &target.save);
+ g_string_set_size (buf, old_len + res);
+}
+
+#if 0
+static char *
+to_png_a (int w, int h, int byte_stride, guint8 *data)
+{
+ cairo_surface_t *surface;
+ struct PngTarget target;
+ gsize res, old_len;
+
+ target.url = g_string_new ("data:image/png;base64,");
+ target.state = 0;
+ target.save = 0;
+
+ surface = cairo_image_surface_create_for_data (data,
+ CAIRO_FORMAT_A8, w, h, byte_stride);
+
+ cairo_surface_write_to_png_stream (surface, write_png_url, &target);
+
+ old_len = target.url->len;
+
+ g_string_set_size (target.url, old_len + 4);
+ res = g_base64_encode_close (FALSE,
+ target.url->str + old_len,
+ &target.state, &target.save);
+ g_string_set_size (target.url, old_len + res);
+
+ return g_string_free (target.url, FALSE);
+}
+#endif
+
+/************************************************************************
+ * Basic I/O primitives *
+ ************************************************************************/
+
+struct BroadwayOutput {
+ GOutputStream *out;
+ GString *buf;
+ int error;
+ guint32 serial;
+ gboolean proto_v7_plus;
+ gboolean binary;
+};
+
+static void
+broadway_output_send_cmd (BroadwayOutput *output,
+ gboolean fin, BroadwayWSOpCode code,
+ const void *buf, gsize count)
+{
+ gboolean mask = FALSE;
+ guchar header[16];
+ size_t p;
+
+ gboolean mid_header = count > 125 && count <= 65535;
+ gboolean long_header = count > 65535;
+
+ /* NB. big-endian spec => bit 0 == MSB */
+ header[0] = ( (fin ? 0x80 : 0) | (code & 0x0f) );
+ header[1] = ( (mask ? 0x80 : 0) |
+ (mid_header ? 126 : long_header ? 127 : count) );
+ p = 2;
+ if (mid_header)
+ {
+ *(guint16 *)(header + p) = GUINT16_TO_BE( (guint16)count );
+ p += 2;
+ }
+ else if (long_header)
+ {
+ *(guint64 *)(header + p) = GUINT64_TO_BE( count );
+ p += 8;
+ }
+ // FIXME: if we are paranoid we should 'mask' the data
+ // FIXME: we should really emit these as a single write
+ g_output_stream_write_all (output->out, header, p, NULL, NULL, NULL);
+ g_output_stream_write_all (output->out, buf, count, NULL, NULL, NULL);
+}
+
+static void
+broadway_output_send_cmd_pre_v7 (BroadwayOutput *output,
+ const void *buf, gsize count)
+{
+ g_output_stream_write_all (output->out, "\0", 1, NULL, NULL, NULL);
+ g_output_stream_write_all (output->out, buf, count, NULL, NULL, NULL);
+ g_output_stream_write_all (output->out, "\xff", 1, NULL, NULL, NULL);
+}
+
+void broadway_output_pong (BroadwayOutput *output)
+{
+ if (output->proto_v7_plus)
+ broadway_output_send_cmd (output, TRUE, BROADWAY_WS_CNX_PONG, NULL, 0);
+}
+
+int
+broadway_output_flush (BroadwayOutput *output)
+{
+ if (output->buf->len == 0)
+ return TRUE;
+
+ if (!output->proto_v7_plus)
+ broadway_output_send_cmd_pre_v7 (output, output->buf->str, output->buf->len);
+ else if (output->binary)
+ broadway_output_send_cmd (output, TRUE, BROADWAY_WS_BINARY,
+ output->buf->str, output->buf->len);
+ else
+ broadway_output_send_cmd (output, TRUE, BROADWAY_WS_TEXT,
+ output->buf->str, output->buf->len);
+
+ g_string_set_size (output->buf, 0);
+
+ return !output->error;
+
+}
+
+BroadwayOutput *
+broadway_output_new (GOutputStream *out, guint32 serial,
+ gboolean proto_v7_plus, gboolean binary)
+{
+ BroadwayOutput *output;
+
+ output = g_new0 (BroadwayOutput, 1);
+
+ output->out = g_object_ref (out);
+ output->buf = g_string_new ("");
+ output->serial = serial;
+ output->proto_v7_plus = proto_v7_plus;
+ output->binary = binary;
+
+ return output;
+}
+
+void
+broadway_output_free (BroadwayOutput *output)
+{
+ g_object_unref (output->out);
+ free (output);
+}
+
+guint32
+broadway_output_get_next_serial (BroadwayOutput *output)
+{
+ return output->serial;
+}
+
+
+/************************************************************************
+ * Core rendering operations *
+ ************************************************************************/
+
+static void
+append_char (BroadwayOutput *output, char c)
+{
+ g_string_append_c (output->buf, c);
+}
+
+static void
+append_bool (BroadwayOutput *output, gboolean val)
+{
+ if (output->binary)
+ g_string_append_c (output->buf, val ? 1: 0);
+ else
+ g_string_append_c (output->buf, val ? '1': '0');
+}
+
+static void
+append_flags (BroadwayOutput *output, guint32 val)
+{
+ if (output->binary)
+ g_string_append_c (output->buf, val);
+ else
+ g_string_append_c (output->buf, val + '0');
+}
+
+
+static void
+append_uint16 (BroadwayOutput *output, guint32 v)
+{
+ gsize old_len = output->buf->len;
+ guint8 *buf;
+
+ if (output->binary)
+ {
+ g_string_set_size (output->buf, old_len + 2);
+ buf = (guint8 *)output->buf->str + old_len;
+ buf[0] = (v >> 0) & 0xff;
+ buf[1] = (v >> 8) & 0xff;
+ }
+ else
+ {
+ g_string_set_size (output->buf, old_len + 3);
+ base64_uint16 (v, output->buf->str + old_len);
+ }
+}
+
+static void
+append_uint32 (BroadwayOutput *output, guint32 v)
+{
+ gsize old_len = output->buf->len;
+ guint8 *buf;
+
+ if (output->binary)
+ {
+ g_string_set_size (output->buf, old_len + 4);
+ buf = (guint8 *)output->buf->str + old_len;
+ buf[0] = (v >> 0) & 0xff;
+ buf[1] = (v >> 8) & 0xff;
+ buf[2] = (v >> 16) & 0xff;
+ buf[3] = (v >> 24) & 0xff;
+ }
+ else
+ {
+ g_string_set_size (output->buf, old_len + 6);
+ base64_uint32 (v, output->buf->str + old_len);
+ }
+}
+
+static void
+overwrite_uint32 (BroadwayOutput *output, gsize pos, guint32 v)
+{
+ if (output->binary)
+ {
+ guint8 *buf = (guint8 *)output->buf->str + pos;
+
+ buf[0] = (v >> 0) & 0xff;
+ buf[1] = (v >> 8) & 0xff;
+ buf[2] = (v >> 16) & 0xff;
+ buf[3] = (v >> 24) & 0xff;
+ }
+ else
+ {
+ base64_uint32 (v, output->buf->str + pos);
+ }
+}
+
+
+static void
+write_header(BroadwayOutput *output, char op)
+{
+ append_char (output, op);
+ append_uint32 (output, output->serial++);
+}
+
+void
+broadway_output_copy_rectangles (BroadwayOutput *output, int id,
+ BroadwayRect *rects, int n_rects,
+ int dx, int dy)
+{
+ int i;
+
+ write_header (output, BROADWAY_OP_COPY_RECTANGLES);
+ append_uint16 (output, id);
+ append_uint16 (output, n_rects);
+ for (i = 0; i < n_rects; i++)
+ {
+ append_uint16 (output, rects[i].x);
+ append_uint16 (output, rects[i].y);
+ append_uint16 (output, rects[i].width);
+ append_uint16 (output, rects[i].height);
+ }
+ append_uint16 (output, dx);
+ append_uint16 (output, dy);
+}
+
+void
+broadway_output_grab_pointer (BroadwayOutput *output,
+ int id,
+ gboolean owner_event)
+{
+ write_header (output, BROADWAY_OP_GRAB_POINTER);
+ append_uint16 (output, id);
+ append_bool (output, owner_event);
+}
+
+guint32
+broadway_output_ungrab_pointer (BroadwayOutput *output)
+{
+ guint32 serial;
+
+ serial = output->serial;
+ write_header (output, BROADWAY_OP_UNGRAB_POINTER);
+
+ return serial;
+}
+
+void
+broadway_output_new_surface(BroadwayOutput *output,
+ int id, int x, int y, int w, int h,
+ gboolean is_temp)
+{
+ write_header (output, BROADWAY_OP_NEW_SURFACE);
+ append_uint16 (output, id);
+ append_uint16 (output, x);
+ append_uint16 (output, y);
+ append_uint16 (output, w);
+ append_uint16 (output, h);
+ append_bool (output, is_temp);
+}
+
+void
+broadway_output_show_surface(BroadwayOutput *output, int id)
+{
+ write_header (output, BROADWAY_OP_SHOW_SURFACE);
+ append_uint16 (output, id);
+}
+
+void
+broadway_output_hide_surface(BroadwayOutput *output, int id)
+{
+ write_header (output, BROADWAY_OP_HIDE_SURFACE);
+ append_uint16 (output, id);
+}
+
+void
+broadway_output_destroy_surface(BroadwayOutput *output, int id)
+{
+ write_header (output, BROADWAY_OP_DESTROY_SURFACE);
+ append_uint16 (output, id);
+}
+
+
+void
+broadway_output_move_resize_surface (BroadwayOutput *output,
+ int id,
+ gboolean has_pos,
+ int x,
+ int y,
+ gboolean has_size,
+ int w,
+ int h)
+{
+ int val;
+
+ if (!has_pos && !has_size)
+ return;
+
+ write_header (output, BROADWAY_OP_MOVE_RESIZE);
+ val = (!!has_pos) | ((!!has_size) << 1);
+ append_uint16 (output, id);
+ append_flags (output, val);
+ if (has_pos)
+ {
+ append_uint16 (output, x);
+ append_uint16 (output, y);
+ }
+ if (has_size)
+ {
+ append_uint16 (output, w);
+ append_uint16 (output, h);
+ }
+}
+
+void
+broadway_output_set_transient_for (BroadwayOutput *output,
+ int id,
+ int parent_id)
+{
+ write_header (output, BROADWAY_OP_SET_TRANSIENT_FOR);
+ append_uint16 (output, id);
+ append_uint16 (output, parent_id);
+}
+
+
+void
+broadway_output_put_rgb (BroadwayOutput *output, int id, int x, int y,
+ int w, int h, int byte_stride, void *data)
+{
+ gsize size_start, image_start, len;
+
+ write_header (output, BROADWAY_OP_PUT_RGB);
+
+ append_uint16 (output, id);
+ append_uint16 (output, x);
+ append_uint16 (output, y);
+
+ size_start = output->buf->len;
+ append_uint32 (output, 0);
+
+ image_start = output->buf->len;
+ if (output->binary)
+ to_png_rgb (output->buf, w, h, byte_stride, (guint32*)data);
+ else
+ to_png_url_rgb (output->buf, w, h, byte_stride, (guint32*)data);
+
+ len = output->buf->len - image_start;
+
+ overwrite_uint32 (output, size_start, len);
+}
+
+typedef struct {
+ int x1, y1;
+ int x2, y2;
+} BroadwayBox;
+
+static int
+is_any_x_set (unsigned char *data,
+ int box_x1, int box_x2,
+ int x1, int x2, int y, int *x_set,
+ int byte_stride)
+{
+ int w ;
+ guint32 *ptr;
+
+ if (x1 < box_x1)
+ x1 = box_x1;
+
+ if (x2 > box_x2)
+ x2 = box_x2;
+
+ w = x2 - x1;
+ if (w > 0)
+ {
+ ptr = (guint32 *)(data + y * byte_stride + x1 * 4);
+ while (w-- > 0)
+ {
+ if (*ptr != 0)
+ {
+ if (x_set)
+ *x_set = x1;
+ return 1;
+ }
+ ptr++;
+ x1++;
+ }
+ }
+ return 0;
+}
+
+
+#define EXTEND_X_FUZZ 10
+#define EXTEND_Y_FUZZ 10
+
+static int
+extend_x_range (unsigned char *data,
+ int box_x1, int box_y1,
+ int box_x2, int box_y2,
+ int *x1, int *x2, int y,
+ int byte_stride)
+{
+ int extended = 0;
+ int new_x;
+
+ while (is_any_x_set (data, box_x1, box_x2, *x1 - EXTEND_X_FUZZ, *x1, y, &new_x, byte_stride))
+ {
+ *x1 = new_x;
+ extended = 1;
+ }
+
+ while (is_any_x_set (data, box_x1, box_x2, *x2, *x2 + EXTEND_X_FUZZ, y, &new_x, byte_stride))
+ {
+ *x2 = new_x + 1;
+ extended = 1;
+ }
+
+ return extended;
+}
+
+static int
+extend_y_range (unsigned char *data,
+ int box_x1, int box_y1,
+ int box_x2, int box_y2,
+ int x1, int x2, int *y,
+ int byte_stride)
+{
+ int extended = 0;
+ int found_set;
+ int yy, y2;
+
+ while (*y < box_y2)
+ {
+ found_set = 0;
+
+ y2 = *y + EXTEND_Y_FUZZ;
+ if (y2 > box_y2)
+ y2 = box_y2;
+
+ for (yy = y2; yy > *y + 1; yy--)
+ {
+ if (is_any_x_set (data, box_x1, box_x2, x1, x2, yy - 1, NULL, byte_stride))
+ {
+ found_set = 1;
+ break;
+ }
+ }
+ if (!found_set)
+ break;
+ *y = yy;
+ extended = 1;
+ }
+
+ return extended;
+}
+
+
+static void
+rgba_find_rects_extents (unsigned char *data,
+ int box_x1, int box_y1,
+ int box_x2, int box_y2,
+ int x, int y,
+ BroadwayBox *rect,
+ int byte_stride)
+{
+ int x1, x2, y1, y2, yy;
+ int extended;
+
+ x1 = x;
+ x2 = x + 1;
+ y1 = y;
+ y2 = y + 1;
+
+ do
+ {
+ /* Expand maximally for all known rows */
+ do
+ {
+ extended = 0;
+
+ for (yy = y1; yy < y2; yy++)
+ extended |= extend_x_range (data,
+ box_x1, box_y1,
+ box_x2, box_y2,
+ &x1, &x2, yy,
+ byte_stride);
+ }
+ while (extended);
+ }
+ while (extend_y_range(data,
+ box_x1, box_y1,
+ box_x2, box_y2,
+ x1, x2, &y2,
+ byte_stride));
+
+ rect->x1 = x1;
+ rect->x2 = x2;
+ rect->y1 = y1;
+ rect->y2 = y2;
+}
+
+static void
+rgba_find_rects_sub (unsigned char *data,
+ int box_x1, int box_y1,
+ int box_x2, int box_y2,
+ int byte_stride,
+ BroadwayBox **rects,
+ int *n_rects, int *alloc_rects)
+{
+ guint32 *line;
+ BroadwayBox rect;
+ int x, y;
+
+ if (box_x1 == box_x2 || box_y1 == box_y2)
+ return;
+
+ for (y = box_y1; y < box_y2; y++)
+ {
+ line = (guint32 *)(data + y * byte_stride + box_x1 * 4);
+
+ for (x = box_x1; x < box_x2; x++)
+ {
+ if (*line != 0)
+ {
+ rgba_find_rects_extents (data,
+ box_x1, box_y1, box_x2, box_y2,
+ x, y, &rect, byte_stride);
+ if (*n_rects == *alloc_rects)
+ {
+ (*alloc_rects) *= 2;
+ *rects = g_renew (BroadwayBox, *rects, *alloc_rects);
+ }
+ (*rects)[*n_rects] = rect;
+ (*n_rects)++;
+ rgba_find_rects_sub (data,
+ box_x1, rect.y1,
+ rect.x1, rect.y2,
+ byte_stride,
+ rects, n_rects, alloc_rects);
+ rgba_find_rects_sub (data,
+ rect.x2, rect.y1,
+ box_x2, rect.y2,
+ byte_stride,
+ rects, n_rects, alloc_rects);
+ rgba_find_rects_sub (data,
+ box_x1, rect.y2,
+ box_x2, box_y2,
+ byte_stride,
+ rects, n_rects, alloc_rects);
+ return;
+ }
+ line++;
+ }
+ }
+}
+
+static BroadwayBox *
+rgba_find_rects (unsigned char *data,
+ int w, int h, int byte_stride,
+ int *n_rects)
+{
+ BroadwayBox *rects;
+ int alloc_rects;
+
+ alloc_rects = 20;
+ rects = g_new (BroadwayBox, alloc_rects);
+
+ *n_rects = 0;
+ rgba_find_rects_sub (data,
+ 0, 0, w, h, byte_stride,
+ &rects, n_rects, &alloc_rects);
+
+ return rects;
+}
+
+void
+broadway_output_put_rgba (BroadwayOutput *output, int id, int x, int y,
+ int w, int h, int byte_stride, void *data)
+{
+ BroadwayBox *rects;
+ int i, n_rects;
+ gsize size_start, image_start, len;
+
+ rects = rgba_find_rects (data, w, h, byte_stride, &n_rects);
+
+ for (i = 0; i < n_rects; i++)
+ {
+ guint8 *subdata;
+
+ write_header (output, BROADWAY_OP_PUT_RGB);
+ append_uint16 (output, id);
+ append_uint16 (output, x + rects[i].x1);
+ append_uint16 (output, y + rects[i].y1);
+
+ size_start = output->buf->len;
+ append_uint32 (output, 0);
+
+ image_start = output->buf->len;
+
+ subdata = (guint8 *)data + rects[i].x1 * 4 + rects[i].y1 * byte_stride;
+ if (output->binary)
+ to_png_rgba (output->buf, rects[i].x2 - rects[i].x1,
+ rects[i].y2 - rects[i].y1,
+ byte_stride, (guint32*)subdata);
+ else
+ to_png_url_rgba (output->buf, rects[i].x2 - rects[i].x1,
+ rects[i].y2 - rects[i].y1,
+ byte_stride, (guint32*)subdata);
+
+ len = output->buf->len - image_start;
+
+ overwrite_uint32 (output, size_start, len);
+ }
+
+ free (rects);
+}
+
+void
+broadway_output_surface_flush (BroadwayOutput *output,
+ int id)
+{
+ write_header (output, BROADWAY_OP_FLUSH);
+ append_uint16 (output, id);
+}
--- /dev/null
+#ifndef __BROADWAY_H__
+#define __BROADWAY_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+#include "broadway-protocol.h"
+
+typedef struct BroadwayOutput BroadwayOutput;
+
+typedef enum {
+ BROADWAY_WS_CONTINUATION = 0,
+ BROADWAY_WS_TEXT = 1,
+ BROADWAY_WS_BINARY = 2,
+ BROADWAY_WS_CNX_CLOSE = 8,
+ BROADWAY_WS_CNX_PING = 9,
+ BROADWAY_WS_CNX_PONG = 0xa
+} BroadwayWSOpCode;
+
+BroadwayOutput *broadway_output_new (GOutputStream *out,
+ guint32 serial,
+ gboolean proto_v7_plus,
+ gboolean binary);
+void broadway_output_free (BroadwayOutput *output);
+int broadway_output_flush (BroadwayOutput *output);
+int broadway_output_has_error (BroadwayOutput *output);
+guint32 broadway_output_get_next_serial (BroadwayOutput *output);
+void broadway_output_new_surface (BroadwayOutput *output,
+ int id,
+ int x,
+ int y,
+ int w,
+ int h,
+ gboolean is_temp);
+void broadway_output_show_surface (BroadwayOutput *output,
+ int id);
+void broadway_output_hide_surface (BroadwayOutput *output,
+ int id);
+void broadway_output_destroy_surface (BroadwayOutput *output,
+ int id);
+void broadway_output_move_resize_surface (BroadwayOutput *output,
+ int id,
+ gboolean has_pos,
+ int x,
+ int y,
+ gboolean has_size,
+ int w,
+ int h);
+void broadway_output_set_transient_for (BroadwayOutput *output,
+ int id,
+ int parent_id);
+void broadway_output_put_rgb (BroadwayOutput *output,
+ int id,
+ int x,
+ int y,
+ int w,
+ int h,
+ int byte_stride,
+ void *data);
+void broadway_output_put_rgba (BroadwayOutput *output,
+ int id,
+ int x,
+ int y,
+ int w,
+ int h,
+ int byte_stride,
+ void *data);
+void broadway_output_surface_flush (BroadwayOutput *output,
+ int id);
+void broadway_output_copy_rectangles (BroadwayOutput *output,
+ int id,
+ BroadwayRect *rects,
+ int n_rects,
+ int dx,
+ int dy);
+void broadway_output_grab_pointer (BroadwayOutput *output,
+ int id,
+ gboolean owner_event);
+guint32 broadway_output_ungrab_pointer (BroadwayOutput *output);
+void broadway_output_pong (BroadwayOutput *output);
+
+#endif /* __BROADWAY_H__ */
+++ /dev/null
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <errno.h>
-#include <cairo.h>
-
-#include "broadway.h"
-#include "broadway-protocol.h"
-
-/************************************************************************
- * Base64 functions *
- ************************************************************************/
-
-static const char base64_alphabet[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-#if 0 /* Unused for now */
-static void
-base64_uint8 (guint8 v, char *c)
-{
- c[0] = base64_alphabet[(v >> 0) & 0x3f];
- c[1] = base64_alphabet[(v >> 6) & 0x3];
-}
-#endif
-
-static void
-base64_uint16 (guint32 v, char *c)
-{
- c[0] = base64_alphabet[(v >> 0) & 0x3f];
- c[1] = base64_alphabet[(v >> 6) & 0x3f];
- c[2] = base64_alphabet[(v >> 12) & 0xf];
-}
-
-#if 0
-static void
-base64_uint24 (guint32 v, char *c)
-{
- c[0] = base64_alphabet[(v >> 0) & 0x3f];
- c[1] = base64_alphabet[(v >> 6) & 0x3f];
- c[2] = base64_alphabet[(v >> 12) & 0x3f];
- c[3] = base64_alphabet[(v >> 18) & 0x3f];
-}
-#endif
-
-static void
-base64_uint32 (guint32 v, char *c)
-{
- c[0] = base64_alphabet[(v >> 0) & 0x3f];
- c[1] = base64_alphabet[(v >> 6) & 0x3f];
- c[2] = base64_alphabet[(v >> 12) & 0x3f];
- c[3] = base64_alphabet[(v >> 18) & 0x3f];
- c[4] = base64_alphabet[(v >> 24) & 0x3f];
- c[5] = base64_alphabet[(v >> 30) & 0x2];
-}
-
-/***********************************************************
- * conversion of raw image data to png data: uris *
- ***********************************************************/
-
-static cairo_status_t
-write_png_data (void *closure,
- const unsigned char *data,
- unsigned int data_len)
-{
- GString *buf = closure;
-
- g_string_append_len (buf, (char *)data, data_len);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-to_png_rgb (GString *buf, int w, int h, int byte_stride, guint32 *data)
-{
- cairo_surface_t *surface;
-
- surface = cairo_image_surface_create_for_data ((guchar *)data,
- CAIRO_FORMAT_RGB24, w, h, byte_stride);
-
- cairo_surface_write_to_png_stream (surface, write_png_data, buf);
- cairo_surface_destroy (surface);
-}
-
-static void
-to_png_rgba (GString *buf, int w, int h, int byte_stride, guint32 *data)
-{
- cairo_surface_t *surface;
-
- surface = cairo_image_surface_create_for_data ((guchar *)data,
- CAIRO_FORMAT_ARGB32, w, h, byte_stride);
-
- cairo_surface_write_to_png_stream (surface, write_png_data, buf);
- cairo_surface_destroy (surface);
-}
-
-struct PngTarget {
- GString *buf;
- int state;
- int save;
-};
-
-static cairo_status_t
-write_png_url (void *closure,
- const unsigned char *data,
- unsigned int data_len)
-{
- struct PngTarget *target = closure;
- gsize res, old_len;
-
- old_len = target->buf->len;
- g_string_set_size (target->buf,
- old_len + (data_len / 3 + 1) * 4 + 4);
-
- res = g_base64_encode_step (data, data_len, FALSE,
- target->buf->str + old_len,
- &target->state, &target->save);
-
- g_string_set_size (target->buf, old_len + res);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-to_png_url_rgb (GString *buf, int w, int h, int byte_stride, guint32 *data)
-{
- cairo_surface_t *surface;
- struct PngTarget target;
- gsize res, old_len;
-
- target.buf = buf;
- target.state = 0;
- target.save = 0;
-
- g_string_append (buf, "data:image/png;base64,");
-
- surface = cairo_image_surface_create_for_data ((guchar *)data,
- CAIRO_FORMAT_RGB24, w, h, byte_stride);
-
- cairo_surface_write_to_png_stream (surface, write_png_url, &target);
- cairo_surface_destroy (surface);
-
- old_len = buf->len;
-
- g_string_set_size (buf, old_len + 4);
- res = g_base64_encode_close (FALSE,
- buf->str + old_len,
- &target.state, &target.save);
- g_string_set_size (buf, old_len + res);
-}
-
-static void
-to_png_url_rgba (GString *buf, int w, int h, int byte_stride, guint32 *data)
-{
- cairo_surface_t *surface;
- struct PngTarget target;
- gsize res, old_len;
-
- target.buf = buf;
- target.state = 0;
- target.save = 0;
-
- g_string_append (buf, "data:image/png;base64,");
-
- surface = cairo_image_surface_create_for_data ((guchar *)data,
- CAIRO_FORMAT_ARGB32, w, h, byte_stride);
-
- cairo_surface_write_to_png_stream (surface, write_png_url, &target);
- cairo_surface_destroy (surface);
-
- old_len = buf->len;
-
- g_string_set_size (buf, old_len + 4);
- res = g_base64_encode_close (FALSE,
- buf->str + old_len,
- &target.state, &target.save);
- g_string_set_size (buf, old_len + res);
-}
-
-#if 0
-static char *
-to_png_a (int w, int h, int byte_stride, guint8 *data)
-{
- cairo_surface_t *surface;
- struct PngTarget target;
- gsize res, old_len;
-
- target.url = g_string_new ("data:image/png;base64,");
- target.state = 0;
- target.save = 0;
-
- surface = cairo_image_surface_create_for_data (data,
- CAIRO_FORMAT_A8, w, h, byte_stride);
-
- cairo_surface_write_to_png_stream (surface, write_png_url, &target);
-
- old_len = target.url->len;
-
- g_string_set_size (target.url, old_len + 4);
- res = g_base64_encode_close (FALSE,
- target.url->str + old_len,
- &target.state, &target.save);
- g_string_set_size (target.url, old_len + res);
-
- return g_string_free (target.url, FALSE);
-}
-#endif
-
-/************************************************************************
- * Basic I/O primitives *
- ************************************************************************/
-
-struct BroadwayOutput {
- GOutputStream *out;
- GString *buf;
- int error;
- guint32 serial;
- gboolean proto_v7_plus;
- gboolean binary;
-};
-
-static void
-broadway_output_send_cmd (BroadwayOutput *output,
- gboolean fin, BroadwayWSOpCode code,
- const void *buf, gsize count)
-{
- gboolean mask = FALSE;
- guchar header[16];
- size_t p;
-
- gboolean mid_header = count > 125 && count <= 65535;
- gboolean long_header = count > 65535;
-
- /* NB. big-endian spec => bit 0 == MSB */
- header[0] = ( (fin ? 0x80 : 0) | (code & 0x0f) );
- header[1] = ( (mask ? 0x80 : 0) |
- (mid_header ? 126 : long_header ? 127 : count) );
- p = 2;
- if (mid_header)
- {
- *(guint16 *)(header + p) = GUINT16_TO_BE( (guint16)count );
- p += 2;
- }
- else if (long_header)
- {
- *(guint64 *)(header + p) = GUINT64_TO_BE( count );
- p += 8;
- }
- // FIXME: if we are paranoid we should 'mask' the data
- // FIXME: we should really emit these as a single write
- g_output_stream_write_all (output->out, header, p, NULL, NULL, NULL);
- g_output_stream_write_all (output->out, buf, count, NULL, NULL, NULL);
-}
-
-static void
-broadway_output_send_cmd_pre_v7 (BroadwayOutput *output,
- const void *buf, gsize count)
-{
- g_output_stream_write_all (output->out, "\0", 1, NULL, NULL, NULL);
- g_output_stream_write_all (output->out, buf, count, NULL, NULL, NULL);
- g_output_stream_write_all (output->out, "\xff", 1, NULL, NULL, NULL);
-}
-
-void broadway_output_pong (BroadwayOutput *output)
-{
- if (output->proto_v7_plus)
- broadway_output_send_cmd (output, TRUE, BROADWAY_WS_CNX_PONG, NULL, 0);
-}
-
-int
-broadway_output_flush (BroadwayOutput *output)
-{
- if (output->buf->len == 0)
- return TRUE;
-
- if (!output->proto_v7_plus)
- broadway_output_send_cmd_pre_v7 (output, output->buf->str, output->buf->len);
- else if (output->binary)
- broadway_output_send_cmd (output, TRUE, BROADWAY_WS_BINARY,
- output->buf->str, output->buf->len);
- else
- broadway_output_send_cmd (output, TRUE, BROADWAY_WS_TEXT,
- output->buf->str, output->buf->len);
-
- g_string_set_size (output->buf, 0);
-
- return !output->error;
-
-}
-
-BroadwayOutput *
-broadway_output_new (GOutputStream *out, guint32 serial,
- gboolean proto_v7_plus, gboolean binary)
-{
- BroadwayOutput *output;
-
- output = g_new0 (BroadwayOutput, 1);
-
- output->out = g_object_ref (out);
- output->buf = g_string_new ("");
- output->serial = serial;
- output->proto_v7_plus = proto_v7_plus;
- output->binary = binary;
-
- return output;
-}
-
-void
-broadway_output_free (BroadwayOutput *output)
-{
- g_object_unref (output->out);
- free (output);
-}
-
-guint32
-broadway_output_get_next_serial (BroadwayOutput *output)
-{
- return output->serial;
-}
-
-
-/************************************************************************
- * Core rendering operations *
- ************************************************************************/
-
-static void
-append_char (BroadwayOutput *output, char c)
-{
- g_string_append_c (output->buf, c);
-}
-
-static void
-append_bool (BroadwayOutput *output, gboolean val)
-{
- if (output->binary)
- g_string_append_c (output->buf, val ? 1: 0);
- else
- g_string_append_c (output->buf, val ? '1': '0');
-}
-
-static void
-append_flags (BroadwayOutput *output, guint32 val)
-{
- if (output->binary)
- g_string_append_c (output->buf, val);
- else
- g_string_append_c (output->buf, val + '0');
-}
-
-
-static void
-append_uint16 (BroadwayOutput *output, guint32 v)
-{
- gsize old_len = output->buf->len;
- guint8 *buf;
-
- if (output->binary)
- {
- g_string_set_size (output->buf, old_len + 2);
- buf = (guint8 *)output->buf->str + old_len;
- buf[0] = (v >> 0) & 0xff;
- buf[1] = (v >> 8) & 0xff;
- }
- else
- {
- g_string_set_size (output->buf, old_len + 3);
- base64_uint16 (v, output->buf->str + old_len);
- }
-}
-
-static void
-append_uint32 (BroadwayOutput *output, guint32 v)
-{
- gsize old_len = output->buf->len;
- guint8 *buf;
-
- if (output->binary)
- {
- g_string_set_size (output->buf, old_len + 4);
- buf = (guint8 *)output->buf->str + old_len;
- buf[0] = (v >> 0) & 0xff;
- buf[1] = (v >> 8) & 0xff;
- buf[2] = (v >> 16) & 0xff;
- buf[3] = (v >> 24) & 0xff;
- }
- else
- {
- g_string_set_size (output->buf, old_len + 6);
- base64_uint32 (v, output->buf->str + old_len);
- }
-}
-
-static void
-overwrite_uint32 (BroadwayOutput *output, gsize pos, guint32 v)
-{
- if (output->binary)
- {
- guint8 *buf = (guint8 *)output->buf->str + pos;
-
- buf[0] = (v >> 0) & 0xff;
- buf[1] = (v >> 8) & 0xff;
- buf[2] = (v >> 16) & 0xff;
- buf[3] = (v >> 24) & 0xff;
- }
- else
- {
- base64_uint32 (v, output->buf->str + pos);
- }
-}
-
-
-static void
-write_header(BroadwayOutput *output, char op)
-{
- append_char (output, op);
- append_uint32 (output, output->serial++);
-}
-
-void
-broadway_output_copy_rectangles (BroadwayOutput *output, int id,
- BroadwayRect *rects, int n_rects,
- int dx, int dy)
-{
- int i;
-
- write_header (output, BROADWAY_OP_COPY_RECTANGLES);
- append_uint16 (output, id);
- append_uint16 (output, n_rects);
- for (i = 0; i < n_rects; i++)
- {
- append_uint16 (output, rects[i].x);
- append_uint16 (output, rects[i].y);
- append_uint16 (output, rects[i].width);
- append_uint16 (output, rects[i].height);
- }
- append_uint16 (output, dx);
- append_uint16 (output, dy);
-}
-
-void
-broadway_output_grab_pointer (BroadwayOutput *output,
- int id,
- gboolean owner_event)
-{
- write_header (output, BROADWAY_OP_GRAB_POINTER);
- append_uint16 (output, id);
- append_bool (output, owner_event);
-}
-
-guint32
-broadway_output_ungrab_pointer (BroadwayOutput *output)
-{
- guint32 serial;
-
- serial = output->serial;
- write_header (output, BROADWAY_OP_UNGRAB_POINTER);
-
- return serial;
-}
-
-void
-broadway_output_new_surface(BroadwayOutput *output,
- int id, int x, int y, int w, int h,
- gboolean is_temp)
-{
- write_header (output, BROADWAY_OP_NEW_SURFACE);
- append_uint16 (output, id);
- append_uint16 (output, x);
- append_uint16 (output, y);
- append_uint16 (output, w);
- append_uint16 (output, h);
- append_bool (output, is_temp);
-}
-
-void
-broadway_output_show_surface(BroadwayOutput *output, int id)
-{
- write_header (output, BROADWAY_OP_SHOW_SURFACE);
- append_uint16 (output, id);
-}
-
-void
-broadway_output_hide_surface(BroadwayOutput *output, int id)
-{
- write_header (output, BROADWAY_OP_HIDE_SURFACE);
- append_uint16 (output, id);
-}
-
-void
-broadway_output_destroy_surface(BroadwayOutput *output, int id)
-{
- write_header (output, BROADWAY_OP_DESTROY_SURFACE);
- append_uint16 (output, id);
-}
-
-
-void
-broadway_output_move_resize_surface (BroadwayOutput *output,
- int id,
- gboolean has_pos,
- int x,
- int y,
- gboolean has_size,
- int w,
- int h)
-{
- int val;
-
- if (!has_pos && !has_size)
- return;
-
- write_header (output, BROADWAY_OP_MOVE_RESIZE);
- val = (!!has_pos) | ((!!has_size) << 1);
- append_uint16 (output, id);
- append_flags (output, val);
- if (has_pos)
- {
- append_uint16 (output, x);
- append_uint16 (output, y);
- }
- if (has_size)
- {
- append_uint16 (output, w);
- append_uint16 (output, h);
- }
-}
-
-void
-broadway_output_set_transient_for (BroadwayOutput *output,
- int id,
- int parent_id)
-{
- write_header (output, BROADWAY_OP_SET_TRANSIENT_FOR);
- append_uint16 (output, id);
- append_uint16 (output, parent_id);
-}
-
-
-void
-broadway_output_put_rgb (BroadwayOutput *output, int id, int x, int y,
- int w, int h, int byte_stride, void *data)
-{
- gsize size_start, image_start, len;
-
- write_header (output, BROADWAY_OP_PUT_RGB);
-
- append_uint16 (output, id);
- append_uint16 (output, x);
- append_uint16 (output, y);
-
- size_start = output->buf->len;
- append_uint32 (output, 0);
-
- image_start = output->buf->len;
- if (output->binary)
- to_png_rgb (output->buf, w, h, byte_stride, (guint32*)data);
- else
- to_png_url_rgb (output->buf, w, h, byte_stride, (guint32*)data);
-
- len = output->buf->len - image_start;
-
- overwrite_uint32 (output, size_start, len);
-}
-
-typedef struct {
- int x1, y1;
- int x2, y2;
-} BroadwayBox;
-
-static int
-is_any_x_set (unsigned char *data,
- int box_x1, int box_x2,
- int x1, int x2, int y, int *x_set,
- int byte_stride)
-{
- int w ;
- guint32 *ptr;
-
- if (x1 < box_x1)
- x1 = box_x1;
-
- if (x2 > box_x2)
- x2 = box_x2;
-
- w = x2 - x1;
- if (w > 0)
- {
- ptr = (guint32 *)(data + y * byte_stride + x1 * 4);
- while (w-- > 0)
- {
- if (*ptr != 0)
- {
- if (x_set)
- *x_set = x1;
- return 1;
- }
- ptr++;
- x1++;
- }
- }
- return 0;
-}
-
-
-#define EXTEND_X_FUZZ 10
-#define EXTEND_Y_FUZZ 10
-
-static int
-extend_x_range (unsigned char *data,
- int box_x1, int box_y1,
- int box_x2, int box_y2,
- int *x1, int *x2, int y,
- int byte_stride)
-{
- int extended = 0;
- int new_x;
-
- while (is_any_x_set (data, box_x1, box_x2, *x1 - EXTEND_X_FUZZ, *x1, y, &new_x, byte_stride))
- {
- *x1 = new_x;
- extended = 1;
- }
-
- while (is_any_x_set (data, box_x1, box_x2, *x2, *x2 + EXTEND_X_FUZZ, y, &new_x, byte_stride))
- {
- *x2 = new_x + 1;
- extended = 1;
- }
-
- return extended;
-}
-
-static int
-extend_y_range (unsigned char *data,
- int box_x1, int box_y1,
- int box_x2, int box_y2,
- int x1, int x2, int *y,
- int byte_stride)
-{
- int extended = 0;
- int found_set;
- int yy, y2;
-
- while (*y < box_y2)
- {
- found_set = 0;
-
- y2 = *y + EXTEND_Y_FUZZ;
- if (y2 > box_y2)
- y2 = box_y2;
-
- for (yy = y2; yy > *y + 1; yy--)
- {
- if (is_any_x_set (data, box_x1, box_x2, x1, x2, yy - 1, NULL, byte_stride))
- {
- found_set = 1;
- break;
- }
- }
- if (!found_set)
- break;
- *y = yy;
- extended = 1;
- }
-
- return extended;
-}
-
-
-static void
-rgba_find_rects_extents (unsigned char *data,
- int box_x1, int box_y1,
- int box_x2, int box_y2,
- int x, int y,
- BroadwayBox *rect,
- int byte_stride)
-{
- int x1, x2, y1, y2, yy;
- int extended;
-
- x1 = x;
- x2 = x + 1;
- y1 = y;
- y2 = y + 1;
-
- do
- {
- /* Expand maximally for all known rows */
- do
- {
- extended = 0;
-
- for (yy = y1; yy < y2; yy++)
- extended |= extend_x_range (data,
- box_x1, box_y1,
- box_x2, box_y2,
- &x1, &x2, yy,
- byte_stride);
- }
- while (extended);
- }
- while (extend_y_range(data,
- box_x1, box_y1,
- box_x2, box_y2,
- x1, x2, &y2,
- byte_stride));
-
- rect->x1 = x1;
- rect->x2 = x2;
- rect->y1 = y1;
- rect->y2 = y2;
-}
-
-static void
-rgba_find_rects_sub (unsigned char *data,
- int box_x1, int box_y1,
- int box_x2, int box_y2,
- int byte_stride,
- BroadwayBox **rects,
- int *n_rects, int *alloc_rects)
-{
- guint32 *line;
- BroadwayBox rect;
- int x, y;
-
- if (box_x1 == box_x2 || box_y1 == box_y2)
- return;
-
- for (y = box_y1; y < box_y2; y++)
- {
- line = (guint32 *)(data + y * byte_stride + box_x1 * 4);
-
- for (x = box_x1; x < box_x2; x++)
- {
- if (*line != 0)
- {
- rgba_find_rects_extents (data,
- box_x1, box_y1, box_x2, box_y2,
- x, y, &rect, byte_stride);
- if (*n_rects == *alloc_rects)
- {
- (*alloc_rects) *= 2;
- *rects = g_renew (BroadwayBox, *rects, *alloc_rects);
- }
- (*rects)[*n_rects] = rect;
- (*n_rects)++;
- rgba_find_rects_sub (data,
- box_x1, rect.y1,
- rect.x1, rect.y2,
- byte_stride,
- rects, n_rects, alloc_rects);
- rgba_find_rects_sub (data,
- rect.x2, rect.y1,
- box_x2, rect.y2,
- byte_stride,
- rects, n_rects, alloc_rects);
- rgba_find_rects_sub (data,
- box_x1, rect.y2,
- box_x2, box_y2,
- byte_stride,
- rects, n_rects, alloc_rects);
- return;
- }
- line++;
- }
- }
-}
-
-static BroadwayBox *
-rgba_find_rects (unsigned char *data,
- int w, int h, int byte_stride,
- int *n_rects)
-{
- BroadwayBox *rects;
- int alloc_rects;
-
- alloc_rects = 20;
- rects = g_new (BroadwayBox, alloc_rects);
-
- *n_rects = 0;
- rgba_find_rects_sub (data,
- 0, 0, w, h, byte_stride,
- &rects, n_rects, &alloc_rects);
-
- return rects;
-}
-
-void
-broadway_output_put_rgba (BroadwayOutput *output, int id, int x, int y,
- int w, int h, int byte_stride, void *data)
-{
- BroadwayBox *rects;
- int i, n_rects;
- gsize size_start, image_start, len;
-
- rects = rgba_find_rects (data, w, h, byte_stride, &n_rects);
-
- for (i = 0; i < n_rects; i++)
- {
- guint8 *subdata;
-
- write_header (output, BROADWAY_OP_PUT_RGB);
- append_uint16 (output, id);
- append_uint16 (output, x + rects[i].x1);
- append_uint16 (output, y + rects[i].y1);
-
- size_start = output->buf->len;
- append_uint32 (output, 0);
-
- image_start = output->buf->len;
-
- subdata = (guint8 *)data + rects[i].x1 * 4 + rects[i].y1 * byte_stride;
- if (output->binary)
- to_png_rgba (output->buf, rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- byte_stride, (guint32*)subdata);
- else
- to_png_url_rgba (output->buf, rects[i].x2 - rects[i].x1,
- rects[i].y2 - rects[i].y1,
- byte_stride, (guint32*)subdata);
-
- len = output->buf->len - image_start;
-
- overwrite_uint32 (output, size_start, len);
- }
-
- free (rects);
-}
-
-void
-broadway_output_surface_flush (BroadwayOutput *output,
- int id)
-{
- write_header (output, BROADWAY_OP_FLUSH);
- append_uint16 (output, id);
-}
+++ /dev/null
-#ifndef __BROADWAY_H__
-#define __BROADWAY_H__
-
-#include <glib.h>
-#include <gio/gio.h>
-#include "broadway-protocol.h"
-
-typedef struct BroadwayOutput BroadwayOutput;
-
-typedef enum {
- BROADWAY_WS_CONTINUATION = 0,
- BROADWAY_WS_TEXT = 1,
- BROADWAY_WS_BINARY = 2,
- BROADWAY_WS_CNX_CLOSE = 8,
- BROADWAY_WS_CNX_PING = 9,
- BROADWAY_WS_CNX_PONG = 0xa
-} BroadwayWSOpCode;
-
-BroadwayOutput *broadway_output_new (GOutputStream *out,
- guint32 serial,
- gboolean proto_v7_plus,
- gboolean binary);
-void broadway_output_free (BroadwayOutput *output);
-int broadway_output_flush (BroadwayOutput *output);
-int broadway_output_has_error (BroadwayOutput *output);
-guint32 broadway_output_get_next_serial (BroadwayOutput *output);
-void broadway_output_new_surface (BroadwayOutput *output,
- int id,
- int x,
- int y,
- int w,
- int h,
- gboolean is_temp);
-void broadway_output_show_surface (BroadwayOutput *output,
- int id);
-void broadway_output_hide_surface (BroadwayOutput *output,
- int id);
-void broadway_output_destroy_surface (BroadwayOutput *output,
- int id);
-void broadway_output_move_resize_surface (BroadwayOutput *output,
- int id,
- gboolean has_pos,
- int x,
- int y,
- gboolean has_size,
- int w,
- int h);
-void broadway_output_set_transient_for (BroadwayOutput *output,
- int id,
- int parent_id);
-void broadway_output_put_rgb (BroadwayOutput *output,
- int id,
- int x,
- int y,
- int w,
- int h,
- int byte_stride,
- void *data);
-void broadway_output_put_rgba (BroadwayOutput *output,
- int id,
- int x,
- int y,
- int w,
- int h,
- int byte_stride,
- void *data);
-void broadway_output_surface_flush (BroadwayOutput *output,
- int id);
-void broadway_output_copy_rectangles (BroadwayOutput *output,
- int id,
- BroadwayRect *rects,
- int n_rects,
- int dx,
- int dy);
-void broadway_output_grab_pointer (BroadwayOutput *output,
- int id,
- gboolean owner_event);
-guint32 broadway_output_ungrab_pointer (BroadwayOutput *output);
-void broadway_output_pong (BroadwayOutput *output);
-
-#endif /* __BROADWAY_H__ */
#include "gdkbroadway-server.h"
-#include "broadway.h"
#include "gdkprivate-broadway.h"
#include <glib.h>
#include "gdkbroadway-server.h"
-#include "broadway.h"
+#include "broadway-output.h"
#include "gdkprivate-broadway.h"
#include <glib.h>
#include "gdkinternals.h"
#include "gdkmain.h"
#include "gdkbroadway-server.h"
-#include "broadway.h"
G_BEGIN_DECLS